<?php

namespace App\Http\Controllers;

use App\BO\OrderStatus\Meta\UserApplyRefundInfo;
use App\BO\OrderStatus\Meta\UserCancelInfo;
use App\BO\OrderStatus\OrderStateDefinition;
use App\BO\OrderStatus\OrderStatus;
use App\Entities\OrderEntity;
use App\ServicesNew\OrderService;
use App\Utils\GenObjFromRequestUtil;
use App\VO\UserOrder\MetaInfo\UserOrderFactory;
use App\VO\UserOrder\MetaInfo\UserOrderSearchInfo;
use App\VO\UserOrder\UserOrderIndexVO;
use App\VO\UserOrder\UserOrderShowVO;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class UserOrderController extends BaseController
{
    // 订单搜索参数
    public const SEARCH_ALL = 0;   // 全部订单
    public const SEARCH_PENDING = 1;  // 待付款
    public const SEARCH_DISTRIBUTION = 2;  // 待分配
    public const SEARCH_WAITING_SERVICE = 3;  // 待上门
    public const SEARCH_WAITING_COMMENT = 4;  // 待评价
    public const SEARCH_REFUND = 5;  // 退款的订单
    public const SEARCH_REVIEWED = 6;  // 已经评价

    /**
     * @api {post} /user/order 用户订单列表
     * @apiGroup UserOrder
     *
     * @apiParam {Number} [type]  订单状态
     */
    /**
     * @param Request $request
     * @param OrderService $orderService
     * @return \Illuminate\Http\JsonResponse
     * @throws \Exception
     */
    public function index(Request $request, OrderService $orderService)
    {
        Log::info('order request', $request->input());

        $userId = $this->getUserId();

        /** * @var UserOrderSearchInfo $search */
        $search = GenObjFromRequestUtil::getObj(UserOrderSearchInfo::class, $request);
        $search->setUserId($userId);
        $search->setOrderStates($this->getSearchOrderStates($request));

        $orderEntities = $orderService->getOrderEntities($search);
        $total = $orderService->count($search);

        $userOrderIndexVO = new UserOrderIndexVO();
        $userOrderIndexVO->setSearch($search);
        $userOrderIndexVO->setTotal($total);

        $now = Carbon::now();

        foreach ($orderEntities as $orderEntity) {
            if ($orderEntity->getOrderState() == OrderStateDefinition::STATE_WAITING_PAY) {
                $this->expireCheck($now, $orderEntity);
            }
            try {
                $orderListInfo = UserOrderFactory::getOrderListInfo($orderEntity);
                $userOrderIndexVO->addOrder($orderListInfo);
            } catch (\Exception $e) {
                Log::warning($e->getMessage());
            }
        }

        return $this->successJsonResult($userOrderIndexVO);
    }

    private function expireCheck(Carbon $now, OrderEntity $orderEntity)
    {
        $ttl = config('app.order_ttl', '1800');
        $expiredAt = Carbon::parse($orderEntity->getCreatedAt())->addSeconds($ttl);

        if ($expiredAt->lt($now)) {
            (new OrderStatus($orderEntity))->getOrderStateContext()->expire();
        }
    }

    /**
     * @param Request $request
     * @return array
     */
    private function getSearchOrderStates(Request $request)
    {
        $searchType = $request->input('type') ?: '';
        switch ($searchType) {
            case self::SEARCH_PENDING:
                $ret = [OrderStateDefinition::STATE_WAITING_PAY];
                break;
            case self::SEARCH_DISTRIBUTION:
                $ret = [OrderStateDefinition::STATE_WAITING_DISTRIBUTION];
                break;
            case self::SEARCH_WAITING_SERVICE:
                $ret = [OrderStateDefinition::STATE_WAITING_SERVICE];
                break;
            case self::SEARCH_WAITING_COMMENT:
                $ret = [OrderStateDefinition::STATE_WAITING_COMMENT];
                break;
            case self::SEARCH_REVIEWED:
                $ret = [OrderStateDefinition::STATE_REVIEWED];
                break;
            case self::SEARCH_REFUND:
                $ret = [OrderStateDefinition::STATE_REFUND_WAITING_CHECK];
                break;
            default:
                $ret = [];
        }

        return $ret;
    }

    /**
     * @api {get} /user/order/{orderId} 用户订单详情
     * @apiGroup UserOrder
     */
    /**
     * @param int $orderId
     * @param OrderService $orderService
     * @return \Illuminate\Http\JsonResponse
     * @throws \Exception
     */
    public function show(int $orderId, OrderService $orderService)
    {
        $orderEntity = $orderService->findOrderEntityByIdAndUserId($orderId, $this->getUserId());
        if (is_null($orderEntity)) {
            return $this->showJsonResult(500, '订单不存在');
        }

        $now = Carbon::now();
        $this->expireCheck($now, $orderEntity);

        $userOrderShowVO = new UserOrderShowVO($orderEntity->getOrderState());
        $userOrderShowVO->setOrder(UserOrderFactory::getOrderInfo($orderEntity));

        return $this->successJsonResult($userOrderShowVO);
    }

    /**
     * @api {post} /user/order/{orderId}/refund 订单申请退款
     * @apiGroup UserOrder
     *
     * @apiParam {String} reason  申请退款原因
     */
    /**
     * @param int $orderId
     * @param Request $request
     * @param OrderService $orderService
     * @return \Illuminate\Http\JsonResponse
     * @throws \Exception
     */
    public function refund(int $orderId, Request $request, OrderService $orderService)
    {
        $orderEntity = $orderService->findOrderEntityByIdAndUserId($orderId, $this->getUserId());
        if (is_null($orderEntity)) {
            return $this->showJsonResult(500, '订单不存在');
        }

        $orderStatus = new OrderStatus($orderEntity);
        if (!$orderStatus->isDistributing()) { // 待分配订单可以申请退款
            return $this->showJsonResult(500, '订单状态不正确');
        }

        $reason = $request->input('reason') ?: '';
        $userApplyRefundInfo = new UserApplyRefundInfo();
        $userApplyRefundInfo->setReason($reason);

        $orderStatus->getOrderStateContext()->applyRefund($userApplyRefundInfo);
        return $this->successJsonResult();
    }

    /**
     * @api {post} /user/order/{orderId}/refundCancel 用户取消退款申请
     * @apiGroup UserOrder
     */
    /**
     * @param int $orderId
     * @param OrderService $orderService
     * @return \Illuminate\Http\JsonResponse
     * @throws \Exception
     */
    public function refundCancel(int $orderId, OrderService $orderService)
    {
        $orderEntity = $orderService->findOrderEntityByIdAndUserId($orderId, $this->getUserId());
        if (is_null($orderEntity)) {
            return $this->showJsonResult(500, '订单不存在');
        }

        $orderStatus = new OrderStatus($orderEntity);
        if (!$orderStatus->isRefundWaitingCheck()) {
            return $this->showJsonResult(500, '订单状态不正确');
        }

        $orderStatus->getOrderStateContext()->userCancelledRefund();
        return $this->successJsonResult();
    }

    /**
     * @api {post} /user/order/{orderId}/cancel 取消订单
     * @apiGroup UserOrder
     *
     * @apiParam {String} reason  用户取消原因
     */
    /**
     * @param int $orderId
     * @param OrderService $orderService
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function cancel(int $orderId, OrderService $orderService, Request $request)
    {
        $orderEntity = $orderService->findOrderEntityByIdAndUserId($orderId, $this->getUserId());
        if (is_null($orderEntity)) {
            return $this->showJsonResult(500, '订单不存在');
        }

        $orderStatus = new OrderStatus($orderEntity);
        if (!$orderStatus->isPending()) { // 末付款的订单可以取消
            return $this->showJsonResult(500, '订单状态不正确');
        }

        $reason = $request->input('reason') ?: '';

        $userCancelInfo = new UserCancelInfo();
        $userCancelInfo->setReason($reason);

        DB::beginTransaction();
        $orderStatus->getOrderStateContext()->userCancel($userCancelInfo);
        DB::commit();

        return $this->successJsonResult();
    }
}
